﻿// GA_2.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include"GA_2.h"

double function_Dixon_Price(const double* x) //Unimodal non-seperable (-10,10)
{
    double Sum = (x[0] - 1) * (x[0] - 1);
    for (unsigned short i = 1; i < chromlength; i++)
        Sum += (i + 1) * (2 * x[i] * x[i] - x[i - 1]) * (2 * x[i] * x[i] - x[i - 1]);
    return Sum;
}

double function_Exponential(const double* x) //Unimodal seperable (-1,1)
{
    double Sum = 0;
    for (unsigned short i = 0; i < chromlength; i++)
        Sum += x[i] * x[i];
    return -exp(-0.5 * Sum);
}

double function_Rosenbrock(const double* x)//unimodal, non,separable (-30,30)
{
    double Sum = 0;
    for (unsigned short i = 0; i < chromlength - 1; i++)
        Sum += 100 * (x[i + 1] - x[i] * x[i]) * (x[i + 1] - x[i] * x[i]) + (x[i] - 1) * (x[i] - 1);
    return Sum;
}

double function_Step(const double* x)//unimodal, Seperable (-100,100)
{
    double Sum = 0;
    for (unsigned short i = 0; i < chromlength; i++)
        Sum += (int(x[i] + 0.5)) * (int(x[i] + 0.5));
    return Sum;
}

double function_Alpine(const double* x) //multimodal, (-10,10)
{
    double Sum = 0;
    for (unsigned int i = 0; i < chromlength; i++)
    {
        Sum += fabs(x[i] * sin(x[i]) + 0.1 * x[i]);
    }
    return Sum;
}

double function_Scaffer(double x, double y)
{
    double TempSum = x * x + y * y;
    double Sum = 0.5 + (sin(sqrt(TempSum)) * sin(sqrt(TempSum)) - 0.5) / ((1 + 0.001 * (TempSum)) * (1 + 0.001 * (TempSum)));
    return Sum;
}

double function_Griewank(const double* x) //multimodal, non-sepearable, (-600,600)
{
    double Sum = 0, Sum1 = 0, Prod = 1;
    for (unsigned short i = 0; i < chromlength; i++)
    {
        Sum1 += x[i] * x[i];
        Prod *= cos(x[i] / sqrt(double(i + 1)));
    }
    Sum = Sum1 / 4000 - Prod + 1;
    return Sum;
}

double function_Salomon(const double* x)
{
    double Sum = 0;
    for (unsigned short i = 0; i < chromlength; i++)
    {
        Sum += x[i] * x[i];
    }
    return 1 - cos(2 * PI * sqrt(Sum)) + 0.1 * sqrt(Sum);
}


double function_InvertedCosineWave(const double* x) //(-5,5)
{
    double Sum = 0;
    for (unsigned short i = 0; i < chromlength - 1; i++)
    {
        double Temp = x[i] * x[i] + x[i + 1] * x[i + 1] + 0.5 * x[i] * x[i + 1];
        Sum -= exp(-Temp / 8) * cos(4 * sqrt(Temp));
    }
    return Sum;
}

double function_Neumaier3(const double* x) // multimodal,separable,(-n*n,n*n)
{
    double Sum = 0, Prod = 1;
    for (unsigned short i = 0; i < chromlength; i++)
        Sum += (x[i] - 1) * (x[i] - 1);
    for (unsigned short i = 1; i < chromlength; i++)
        Prod += x[i] * x[i - 1];
    return Sum - Prod;
}

//创建初始解
void InitialPopulation(struct individual* population, double minValue, double maxValue, int INDEX)
{
    for (int i = 0; i < POPSIZE; i++)
    {
        if (INDEX == 6) //Scaffer’s function
        {
            population[i].chrom[0] = minValue + (maxValue - minValue) * rand() / RAND_MAX;
            population[i].chrom[1] = minValue + (maxValue - minValue) * rand() / RAND_MAX;
        }
        else
        {
            for (int j = 0; j < chromlength; j++)
                population[i].chrom[j] = minValue + (maxValue - minValue) * rand() / RAND_MAX;
        }      
    }
}

//选择操作
void Select(struct individual* population)
{
    struct individual mewpopulation[POPSIZE];
    int i, index;
    double p, sum = 0;
    double cfitness[POPSIZE];

    for (i = 0; i < POPSIZE; i++)
        sum += population[i].fitness;

    for (i = 0; i < POPSIZE; i++)
        cfitness[i] = population[i].fitness / sum;

    for (i = 1; i < POPSIZE; i++)
        cfitness[i] = cfitness[i - 1] + cfitness[i];

    for (i = 0; i < POPSIZE; i++)
    {
        p = rand() % 1000 / 1000.0;
        index = 0;
        while (p > cfitness[index])
            index++;
        mewpopulation[i] = population[index];
    }

    for (i = 0; i < POPSIZE; i++)
        population[i] = mewpopulation[i];
}

//交叉操作-算术交叉算子
void Crossover(struct individual* population)
{
    struct individual mewpopulation[POPSIZE];
    double p;
    int i,j;
    vector<int> v;

    for (i = 0; i < POPSIZE; i++)
        v.push_back(i);
   
    random_shuffle(v.begin(), v.end());     //洗牌操作
   
    for (i = 0; i < POPSIZE - 1; i += 2)
    {
        p = rand() % 1000 / 1000.0;
        if (p < pc)
        {
            double alfa = 0.5;
            for (j = 0; j < chromlength; j++)
            {
                mewpopulation[i].chrom[j] = population[v[i]].chrom[j] * alfa + population[v[i + 1]].chrom[j] * (1.0 - alfa);
                mewpopulation[i+1].chrom[j] = population[v[i]].chrom[j] * (1.0-alfa) + population[v[i + 1]].chrom[j] * alfa;
            }
        }
    }
    for (i = 0; i < POPSIZE; i++)
        population[i] = mewpopulation[i];
}

void Mutation(struct individual* population, double minValue, double maxValue)
{
    int i, j, k;
    double p;
    double eta = (maxValue - minValue) * rand() / RAND_MAX * 0.05;

    for (i = 0; i < POPSIZE; i++) {
        for (j = 0; j < chromlength; j++) {
            p = rand() % 1000 / 1000.0;
            if (p < pm) 
            {
                if(rand()%2)
                    population[i].chrom[j] = population[i].chrom[j] + eta;
                else
                    population[i].chrom[j] = population[i].chrom[j] - eta;

                if (population[i].chrom[j] < minValue)
                    population[i].chrom[j] = minValue;
                else if (population[i].chrom[j] > maxValue)
                    population[i].chrom[j] = maxValue;
            }
        }
    }
}

//计算目标函数值和适应度值
void Evaluate(struct individual* population, int INDEX)
{
    int i;
    switch (INDEX)
    {
    case 1:
        for (i = 0; i < POPSIZE; i++)
        {
            population[i].value = function_Dixon_Price(population[i].chrom);
            population[i].fitness = 1.0 / population[i].value;
        }
        break;
    case 2:
        for (i = 0; i < POPSIZE; i++)
        {
            population[i].value = function_Exponential(population[i].chrom);
            population[i].fitness = 1.0 / population[i].value;
        }
        break;
    case 3:
        for (i = 0; i < POPSIZE; i++)
        {
            population[i].value = function_Rosenbrock(population[i].chrom);
            population[i].fitness = 1.0 / population[i].value;
        }
        break;
    case 4:
        for (i = 0; i < POPSIZE; i++)
        {
            population[i].value = function_Step(population[i].chrom);
            population[i].fitness = 1.0 / population[i].value;
        }
        break;
    case 5:
        for (i = 0; i < POPSIZE; i++)
        {
            population[i].value = function_Alpine(population[i].chrom);
            population[i].fitness = 1.0 / population[i].value;
        }
        break;
    case 6: //Scaffer’s function
        for (i = 0; i < POPSIZE; i++)
        {
            population[i].value = function_Scaffer(population[i].chrom[0], population[i].chrom[1]);
            population[i].fitness = 1.0 / population[i].value;
        }
        break;
    case 7:
        for (i = 0; i < POPSIZE; i++)
        {
            population[i].value = function_Griewank(population[i].chrom);
            population[i].fitness = 1.0 / population[i].value;
        }
        break;
    case 8:
        for (i = 0; i < POPSIZE; i++)
        {
            population[i].value = function_Salomon(population[i].chrom);
            population[i].fitness = 1.0 / population[i].value;
        }
        break;
    case 9:
        for (i = 0; i < POPSIZE; i++)
        {
            population[i].value = function_InvertedCosineWave(population[i].chrom);
            population[i].fitness = 1.0 / population[i].value;
        }
        break;
    case 10:
        for (i = 0; i < POPSIZE; i++)
        {
            population[i].value = function_Neumaier3(population[i].chrom);
            population[i].fitness = 1.0 / population[i].value;
        }
        break;
    default:
        cout << "Error in Function Evaluate" << endl;
    }
}

//更新当前最优解
void UpdateCurBest(struct individual* population, struct individual &currentbest)
{
    int i, bestIndex = 0;
    double bestValue = population[0].value;
    for (i = 1; i < POPSIZE; i++)
    {
        if (population[i].value < bestValue)
        {
            bestValue = population[i].value;
            bestIndex = i;
        }
    }
    currentbest = population[bestIndex];
}

void OutPut(int INDEX)
{
    switch (INDEX)
    {
    case 1:
        cout << "目前测试函数为：function_Dixon_Price" << endl;
        break;
    case 2:
        cout << "目前测试函数为：function_Exponential" << endl;
        break;
    case 3:
        cout << "目前测试函数为：function_Rosenbrock" << endl;
        break;
    case 4:
        cout << "目前测试函数为：function_Step" << endl;
        break;
    case 5:
        cout << "目前测试函数为：function_Alpine" << endl;
        break;
    case 6:
        cout << "目前测试函数为：function_Scaffer" << endl;
        break;
    case 7:
        cout << "目前测试函数为：function_Griewank" << endl;
        break;
    case 8:
        cout << "目前测试函数为：function_Salomon" << endl;
        break;
    case 9:
        cout << "目前测试函数为：function_InvertedCosineWave" << endl;
        break;
    case 10:
        cout << "目前测试函数为：function_Neumaier3" << endl;
        break;
    default:
        cout << "Error in Function OutPut" << endl;
    }
}

void SetMaxMinValue(double& maxValue, double& minValue, int INDEX)
{
    switch (INDEX)
    {
    case 1:
        maxValue = 10.0;
        minValue = -10.0;
        break;
    case 2:
        maxValue = 1.0;
        minValue = -1.0;
        break;
    case 3:
        maxValue = 30.0;
        minValue = -30.0;
        break;
    case 4:
        maxValue = 100.0;
        minValue = -100.0;
        break;
    case 5:
        maxValue = 10.0;
        minValue = -10.0;
        break;
    case 6:
        maxValue = 100.0;
        minValue = -100.0;
        break;
    case 7:
        maxValue = 600.0;
        minValue = -600.0;
        break;
    case 8:
        maxValue = 100.0;
        minValue = -100.0;
        break;
    case 9:
        maxValue = 5.0;
        minValue = -5.0;
        break;
    case 10:
        maxValue = chromlength * chromlength;
        minValue = -1.0 * maxValue;
        break;
    default:
        cout << "Error in Function SetMaxMinValue" << endl;
    }
}


void main()
{
    int curgen = 1;      //当前代数

    struct individual currentbest;        //当前已搜索到的最优个体
    struct individual population[POPSIZE];
    
    double maxValue, minValue;

    SetMaxMinValue(maxValue, minValue, INDEX);
    OutPut(INDEX);

    InitialPopulation(population, minValue, maxValue, INDEX);
    Evaluate(population, INDEX);
    UpdateCurBest(population, currentbest);

    while (curgen <= maxgeneration)
    {
        Select(population);
        Crossover(population);
        Evaluate(population, INDEX);
        UpdateCurBest(population, currentbest);
        Mutation(population, minValue, maxValue);
        Evaluate(population, INDEX);
        UpdateCurBest(population, currentbest);
        curgen++;
    }

    cout << "最优解的目标函数值为: " << currentbest.value << endl;
    cout << "该最优解各个决策变量值为:" << endl;
    for (int i = 0; i < chromlength; i++)
    {
        cout << currentbest.chrom[i] << endl;
    }
}
